package com.sijiao.common;

import com.sijiao.controller.ReceiveData;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
import org.springframework.stereotype.Component;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 远程调用接口的方法
 *
 * @author ShiLian
 * @date 2022/07/19 01:01
 **/
@Component
public class HttpClientUtil {

    private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class);


    /**
     * 向远程接口发起请求，返回字符串类型结果()
     *
     * @param url           接口地址
     * @param requestMethod 请求方式
     * @param params        传递参数
     * @return 返回结果
     */
    public static String httpRequestToString(String url, String requestMethod, Map<String, String> params) {
        String result = null;
        try {
            InputStream inputStream = httpRequestToStream(url, requestMethod, params);
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            result = new String(bytes);
        } catch (IOException e) {
            log.error("HttpClientUtil httpRequestToStream UnsupportedEncodingException is happened!" + e);
            return "HttpClientUtil httpRequestToStream UnsupportedEncodingException is happened!";
        }
        return result;
    }

    /**
     * 向远程接口发起骑牛，返回字节流（可以用来读取文件）
     *
     * @param url
     * @param requestMethod
     * @param params
     * @return
     */
    public static InputStream httpRequestToStream(String url, String requestMethod, Map<String, String> params) {
        InputStream inputStream = null;
        try {
            String parameters = "";
            boolean hasParams = false;
            // 将参数集合拼接成特定格式
            for (String key : params.keySet()) {
                String value = URLEncoder.encode(params.get(key), "UTF-8");
                parameters += key + "=" + value + "&";
                hasParams = true;
            }
            if (hasParams) {
                parameters = parameters.substring(0, parameters.length() - 1);
            }
            // 如果请求方式为get
            boolean isGet = "get".equalsIgnoreCase(requestMethod);
            // 如果请求方式为post
            boolean isPost = "posy".equalsIgnoreCase(requestMethod);
            if (isGet) {
                url += "?" + parameters;
            }
            URL uu = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) uu.openConnection();
            // 请求的参数类型（使用restlet框架时，为了兼容框架，必须设置Content-Type为“”或空）
            connection.setRequestProperty("Content-Type", "application/octet-stream");
            // conn.setRequestProperty("Content-Type",""application/x-www-form-urlencoded)
            // 设置连接时间
            connection.setConnectTimeout(50000);
            // 设置读取返回内容超时时间
            connection.setReadTimeout(50000);
            //设置向HttpURLConnection对象中输出，因为post方式将方式将请求参数放在http正文内，因此需要设置为true,默认false
            if (isPost) {
                connection.setDoOutput(true);
            }
            // 设置从HttpURLConnection对象读入，默认为true
            connection.setDoInput(true);
            if (isPost) {
                connection.setUseCaches(false);
            }
            // 设置请求方式，默认为GET
            connection.setRequestMethod(requestMethod);

            // post方式需要将传递的参数输出到conn对象中
            if (isPost) {
                DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
                dos.writeBytes(parameters);
                dos.flush();
                dos.close();
            }
            // 从HttpURLConnection对象中读取响应的消息
            // 执行该语句时才正式发起请求
            inputStream = connection.getInputStream();
        } catch (UnsupportedEncodingException e) {
            log.error("HttpClientUtil httpRequestToStream UnsupportedEncodingException is happened!" + e);
            return inputStream;
        } catch (MalformedURLException e) {
            log.error("HttpClientUtil httpRequestToStream MalformedURLException is happened!" + e);
            return inputStream;
        } catch (IOException e) {
            log.error("HttpClientUtil httpRequestToStream IOException is happened!" + e);
            return inputStream;
        }
        return inputStream;
    }

    public static String httpRequestToString(String url, String requestMethod, Map<String, String> params, String... auth) {
        String methodResult = null;
        try {
            String parameters = "";
            boolean hasParams = false;
            for (String key : params.keySet()) {
                String value = URLEncoder.encode(params.get(key), "UTF-8");
                parameters += key + "=" + value + "&";
                hasParams = true;
            }
            if (hasParams) {
                parameters = parameters.substring(0, parameters.length() - 1);
            }
            // 是否为GET方式请求
            boolean isGet = "get".equalsIgnoreCase(requestMethod);
            boolean isPost = "post".equalsIgnoreCase(requestMethod);
            boolean isPut = "put".equalsIgnoreCase(requestMethod);
            boolean isDelete = "delete".equalsIgnoreCase(requestMethod);

            // 创建HttpClient连接对象
            HttpClient client = HttpClientBuilder.create().build();
            HttpRequestBase method = null;
            if (isGet) {
                url += "?" + parameters;
                method = new HttpGet();
            } else if (isPost) {
                method = new HttpPost(url);
                HttpPost postMethod = (HttpPost) method;
                StringEntity entity = new StringEntity(parameters);
                postMethod.setEntity(entity);
            } else if (isPut) {
                method = new HttpPut(url);
                HttpPut putMethod = (HttpPut) method;
                StringEntity entity = new StringEntity(parameters);
                putMethod.setEntity(entity);
            } else if (isDelete) {
                url += "?" + parameters;
                method = new HttpDelete(url);
            }
            HttpClientContext context = null;
            if (!(auth == null || auth.length == 0)) {
                String username = auth[0];
                String password = auth[1];
                UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username,password);
                CredentialsProvider provider = new BasicCredentialsProvider();
                provider.setCredentials(AuthScope.ANY,credentials);
                context = HttpClientContext.create();
                context.setCredentialsProvider(provider);
            }
            HttpResponse response = client.execute(method,context);
            if (response.getStatusLine().getStatusCode() == 200){
                methodResult = EntityUtils.toString(response.getEntity());
            }
        } catch (UnsupportedEncodingException e){
            log.error("HttpClientUtil httpRequestToString UnsupportedEncodingException is happened!" + e);
            return "HttpClientUtil httpRequestToString UnsupportedEncodingException is happened!";
        }catch (IOException e){
            log.error("HttpClientUtil httpRequestToString IOException is happened!" + e);
            return "HttpClientUtil httpRequestToString IOException is happened!";
        }
        return methodResult;
    }
}
